package org.wmq.positiontoshop.common;

import io.minio.*;
import io.minio.Result;
import io.minio.errors.*;
import io.minio.http.Method;
import io.minio.messages.Bucket;
import io.minio.messages.Item;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.InputStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Minio客户端工具类，用于操作Minio对象存储
 */
@Component
public class MinioClient {

    private final io.minio.MinioClient minioClient;

    /**
     * 构造函数，初始化Minio客户端
     *
     * @param endpoint        Minio服务地址
     * @param accessKey       访问密钥
     * @param secretKey       密钥
     * @param secure          是否使用HTTPS
     */
    public MinioClient(@Value("${minio.endpoint}") String endpoint,
                      @Value("${minio.accessKey}") String accessKey,
                      @Value("${minio.secretKey}") String secretKey,
                      @Value("${minio.secure:false}") boolean secure) {
        this.minioClient = io.minio.MinioClient.builder()
                .endpoint(endpoint, secure ? 443 : 9000, secure)
                .credentials(accessKey, secretKey)
                .build();
    }

    /**
     * 创建存储桶
     *
     * @param bucketName 存储桶名称
     * @throws Exception 创建失败时抛出异常
     */
    public void createBucket(String bucketName) throws Exception {
        boolean found = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
        if (!found) {
            minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
        }
    }

    /**
     * 列出所有存储桶
     *
     * @return 存储桶列表
     * @throws Exception 操作失败时抛出异常
     */
    public List<String> listBuckets() throws Exception {
        return minioClient.listBuckets().stream().map(Bucket::name).toList();
    }

    /**
     * 删除存储桶
     *
     * @param bucketName 存储桶名称
     * @throws Exception 删除失败时抛出异常
     */
    public void deleteBucket(String bucketName) throws Exception {
        minioClient.removeBucket(RemoveBucketArgs.builder().bucket(bucketName).build());
    }

    /**
     * 上传文件
     *
     * @param bucketName  存储桶名称
     * @param objectName  对象名称
     * @param inputStream 文件输入流
     * @param size        文件大小
     * @param contentType 文件类型
     * @throws Exception 上传失败时抛出异常
     */
    public void uploadObject(String bucketName, String objectName, InputStream inputStream, long size, String contentType) throws Exception {
        minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .stream(inputStream, size, -1)
                        .contentType(contentType)
                        .build()
        );
    }

    /**
     * 下载文件
     *
     * @param bucketName 存储桶名称
     * @param objectName 对象名称
     * @return 文件输入流
     * @throws Exception 下载失败时抛出异常
     */
    public InputStream downloadObject(String bucketName, String objectName) throws Exception {
        return minioClient.getObject(
                GetObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .build()
        );
    }

    /**
     * 删除文件
     *
     * @param bucketName 存储桶名称
     * @param objectName 对象名称
     * @throws Exception 删除失败时抛出异常
     */
    public void deleteObject(String bucketName, String objectName) throws Exception {
        minioClient.removeObject(
                RemoveObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .build()
        );
    }

    /**
     * 列出存储桶中的所有文件
     *
     * @param bucketName 存储桶名称
     * @return 文件列表
     * @throws Exception 操作失败时抛出异常
     */
    public List<String> listObjects(String bucketName) throws Exception {
        List<String> objectNames = new ArrayList<>();
        Iterable<Result<Item>> results = minioClient.listObjects(
                ListObjectsArgs.builder()
                        .bucket(bucketName)
                        .recursive(true)
                        .build()
        );
        for (Result<Item> result : results) {
            Item item = result.get();
            objectNames.add(item.objectName());
        }
        return objectNames;


    }

    /**
     * 获取文件信息
     *
     * @param bucketName 存储桶名称
     * @param objectName 对象名称
     * @return 文件信息
     * @throws Exception 操作失败时抛出异常
     */
    public ObjectStat getObjectInfo(String bucketName, String objectName) throws Exception {
        StatObjectResponse response = minioClient.statObject(
                StatObjectArgs.builder()
                        .bucket(bucketName)
                        .object(objectName)
                        .build()
        );
        return new ObjectStat(
                response.bucket(),
                response.object(),
                response.size(),
                response.etag(),
                response.lastModified().toString(),
                response.contentType()
        );
    }

    /**
     * 生成文件临时访问URL
     *
     * @param bucketName 存储桶名称
     * @param objectName 对象名称
     * @param expires    过期时间（秒）
     * @return 临时访问URL
     * @throws Exception 生成失败时抛出异常
     */
    public String getPresignedObjectUrl(String bucketName, String objectName, int expires) throws Exception {
        return minioClient.getPresignedObjectUrl(
                GetPresignedObjectUrlArgs.builder()
                        .method(Method.GET)
                        .bucket(bucketName)
                        .object(objectName)
                        .expiry(expires, TimeUnit.SECONDS)
                        .build()
        );
    }

    /**
     * 文件信息类
     */
    public static class ObjectStat {
        private final String bucketName;
        private final String objectName;
        private final long size;
        private final String etag;
        private final String lastModified;
        private final String contentType;

        public ObjectStat(String bucketName, String objectName, long size, String etag, String lastModified, String contentType) {
            this.bucketName = bucketName;
            this.objectName = objectName;
            this.size = size;
            this.etag = etag;
            this.lastModified = lastModified;
            this.contentType = contentType;
        }

        // Getter methods
        public String getBucketName() {
            return bucketName;
        }

        public String getObjectName() {
            return objectName;
        }

        public long getSize() {
            return size;
        }

        public String getEtag() {
            return etag;
        }

        public String getLastModified() {
            return lastModified;
        }

        public String getContentType() {
            return contentType;
        }

        @Override
        public String toString() {
            return "ObjectStat{" +
                    "bucketName='" + bucketName + '\'' +
                    ", objectName='" + objectName + '\'' +
                    ", size=" + size +
                    ", etag='" + etag + '\'' +
                    ", lastModified='" + lastModified + '\'' +
                    ", contentType='" + contentType + '\'' +
                    '}';
        }
    }
}